#include <IDK.hpp>
#include <Renderer.hpp>
#include <RenderState.hpp>

namespace Renderer
{
	/* TRenderer */
	TRenderer::TRenderer() 
		: Base(),
		mPasses(new Passes::Create()),
		mLockReset(false)
	{}

	//-------------------------------------------------------
	// OnStart
	//-------------------------------------------------------
	void TRenderer::OnStart(void)
	{
		ThreadStart();
		OnActive(true);
	}

	//-------------------------------------------------------
	// OnInit
	//-------------------------------------------------------
	void TRenderer::OnInit(void)
	{
	}

	//-------------------------------------------------------
	// OnFinish
	//-------------------------------------------------------
	void TRenderer::OnFinish(void)
	{
		if(mViewport != NullPtr)
		{
			iError("Viewport assigned need fisrt detach viewport");
		}

		ClearPasses();
	}

	//-------------------------------------------------------
	// OnUpdate
	//-------------------------------------------------------
	void TRenderer::OnUpdate(float dt)
	{
		Base::Update(dt);
	}

	//-------------------------------------------------------
	// SetViewport
	//-------------------------------------------------------
	void TRenderer::SetViewport(ref<IDK::IViewport> viewport)
	{
		if(mViewport != NullPtr)
		{
			ThreadSyncExit();
			iLog("Renderer module stop...");
		}
		mPasses->Clear();
		mViewport = viewport;
	}

	//-------------------------------------------------------
	// BeginRender
	//-------------------------------------------------------
	void TRenderer::BeginRender()
	{
		CheckResetDevice();

		if(mActive)
		{
			for(Passes::Iterator it = mPasses->Begin(), end = mPasses->End(); it!=end; ++it)
			{
				it->Render(*mRenderState);
				//step in to?
				it->Rendered(*mRenderState);
			}
		}
	}

	//-------------------------------------------------------
	// EndRender
	//-------------------------------------------------------
	void TRenderer::EndRender(void)
	{
	}

	//-------------------------------------------------------
	// Swap
	//-------------------------------------------------------
	void TRenderer::Swap(float dt)
	{
		mRenderState->Swap(dt);

		mContext->SwapBuffers();
	}

	//-------------------------------------------------------
	// OnThreadStart
	//-------------------------------------------------------
	void TRenderer::OnThreadStart(void)
	{
		mNeedReset = false;
		mActive = true;

		mContext = CreateContext();
		mRenderState = CreateRenderState();

		Base::OnThreadStart();
	}

	//-------------------------------------------------------
	// OnThreadStop
	//-------------------------------------------------------
	void TRenderer::OnThreadStop(void)
	{
		mNeedReset = true;
		CheckResetDevice();
		//free context
		mRenderState = NullPtr;
		mContext = NullPtr;

		Base::OnThreadStop();
	}

	//-------------------------------------------------------
	// OnThreadLock
	//-------------------------------------------------------
	void TRenderer::OnThreadLock(void)
	{
		mNeedReset = mLockReset;
		CheckResetDevice();
	}

	//-------------------------------------------------------
	// OnThreadUpdate
	//-------------------------------------------------------
	bool TRenderer::OnThreadUpdate(float dt, bool ready)
	{
		BeginRender();
		Swap(dt);

		return Base::OnThreadUpdate(dt, ready);
	}

	//-------------------------------------------------------
	// CreateGetViewportViewport
	//-------------------------------------------------------
	ref<IDK::IViewport> TRenderer::GetViewport(void)
	{
		return mViewport;
	}

	//-------------------------------------------------------
	// ::Active
	//-------------------------------------------------------
	void TRenderer::OnActive(bool active)
	{
		mActive = active;
	}
	//-------------------------------------------------------
	// ::Reset
	//-------------------------------------------------------
	void TRenderer::CheckResetDevice(void)
	{
		if(mNeedReset)
		{
			//Do reset resources
			//...
			//Reset();
			mRenderState->Reset();

			mNeedReset = false;
		}
	}

	//-------------------------------------------------------
	// ::AddPass
	//-------------------------------------------------------
	void TRenderer::AddPass(ref<IDK::IRenderer::IPass> pass)
	{
		mPasses->Add(pass);
	}

	//-------------------------------------------------------
	// ::AddPass
	//-------------------------------------------------------
	void TRenderer::ClearPasses(void)
	{
		mPasses->Clear();
	}

	//-------------------------------------------------------
	// ::Lock
	//-------------------------------------------------------
	void TRenderer::Lock(bool reset)
	{
		mLockReset = reset;

		ThreadLock();

		mLockReset = false;
	}

	//-------------------------------------------------------
	// ::Unlock
	//-------------------------------------------------------
	void TRenderer::Unlock(void)
	{
		ThreadUnlock();
	}
}